msg_tool\utils\psd/
compression.rs

1use super::NormalLayer;
2use super::types::*;
3use crate::ext::io::*;
4use anyhow::Result;
5use std::io::Read;
6
7pub fn rle_compress(data: &[u8]) -> Vec<u8> {
8    let start = 0;
9    let line_end = data.len();
10    let mut idx = start;
11    let mut literal: Vec<u8> = Vec::new();
12    let mut out_line: Vec<u8> = Vec::new();
13    while idx < line_end {
14        // detect run length at current position
15        let mut run_len = 1;
16        while idx + run_len < line_end && data[idx + run_len] == data[idx] && run_len < 128 {
17            run_len += 1;
18        }
19
20        if run_len >= 3 {
21            // flush any pending literals
22            if !literal.is_empty() {
23                // header = literal_len - 1 (0..127)
24                let header = (literal.len() - 1) as i8;
25                out_line.push(header as u8);
26                out_line.extend_from_slice(&literal);
27                literal.clear();
28            }
29            // write run: header = -(run_len - 1), then single byte value
30            let header = -(((run_len as u8) - 1) as i8);
31            out_line.push(header as u8);
32            out_line.push(data[idx]);
33            idx += run_len;
34        } else {
35            // collect literal bytes until a run of >=3 or 128 reached
36            literal.push(data[idx]);
37            idx += 1;
38            // if literal is full, flush it
39            if literal.len() == 128 {
40                let header = (literal.len() - 1) as i8;
41                out_line.push(header as u8);
42                out_line.extend_from_slice(&literal);
43                literal.clear();
44            } else {
45                // peek ahead: if next starts a run >=3, flush literal now
46                if idx < line_end {
47                    let mut look_run = 1;
48                    while idx + look_run < line_end
49                        && data[idx + look_run] == data[idx]
50                        && look_run < 128
51                    {
52                        look_run += 1;
53                    }
54                    if look_run >= 3 {
55                        if !literal.is_empty() {
56                            let header = (literal.len() - 1) as i8;
57                            out_line.push(header as u8);
58                            out_line.extend_from_slice(&literal);
59                            literal.clear();
60                        }
61                    }
62                }
63            }
64        }
65    }
66    // flush remaining literal
67    if !literal.is_empty() {
68        let header = (literal.len() - 1) as i8;
69        out_line.push(header as u8);
70        out_line.extend_from_slice(&literal);
71        literal.clear();
72    }
73    out_line
74}
75
76pub fn rle_decompress(data: &[u8]) -> Result<Vec<u8>> {
77    let mut reader = MemReaderRef::new(data);
78    let len = data.len();
79    let mut out = Vec::new();
80    while reader.pos < len {
81        let c = reader.read_i8()?;
82        if c >= 0 {
83            let rlen = (c as usize) + 1;
84            let old_len = out.len();
85            out.resize(old_len + rlen, 0);
86            reader.read_exact(&mut out[old_len..old_len + rlen])?;
87        } else {
88            let rlen = (-(c as isize) as usize) + 1;
89            let val = reader.read_u8()?;
90            let old_len = out.len();
91            out.resize(old_len + rlen, val);
92        }
93    }
94    Ok(out)
95}
96
97pub fn decompress_channel_image_data(
98    data: &mut ChannelImageData,
99    layer: &NormalLayer,
100) -> Result<()> {
101    match data.compression {
102        0 => Ok(()), // no compression
103        1 => {
104            let mut reader = MemReaderRef::new(&data.image_data);
105            let base = &layer.layer.base;
106            let height = (base.bottom - base.top) as u32;
107            let length_len = height as usize * 2;
108            let mut start = length_len;
109            let mut image = Vec::new();
110            for _ in 0..height {
111                let len = reader.read_u16_be()? as usize;
112                let decompressed = rle_decompress(&data.image_data[start..start + len])?;
113                start += len;
114                image.extend(decompressed);
115            }
116            data.image_data = image;
117            data.compression = 0;
118            Ok(())
119        }
120        2 => {
121            let mut decoder = flate2::read::ZlibDecoder::new(&data.image_data[..]);
122            let mut decompressed = Vec::new();
123            decoder.read_to_end(&mut decompressed)?;
124            data.image_data = decompressed;
125            data.compression = 0;
126            Ok(())
127        }
128        3 => {
129            let mut decoder = flate2::read::ZlibDecoder::new(&data.image_data[..]);
130            let mut decompressed = Vec::new();
131            decoder.read_to_end(&mut decompressed)?;
132            let base = &layer.layer.base;
133            let height = (base.bottom - base.top) as u32;
134            let width = (base.right - base.left) as u32;
135            let bit_depth = layer.psd.bit_depth();
136            if bit_depth == 1 {
137                anyhow::bail!("Decompression for 1-bit images is not implemented yet");
138            }
139            let mut writer = MemWriterRef::new(&mut decompressed);
140            for _ in 0..height {
141                if bit_depth == 8 {
142                    let mut pre = writer.read_u8()?;
143                    for _ in 1..width {
144                        let cur = writer.peek_u8()?;
145                        let val = cur.wrapping_add(pre);
146                        writer.write_u8(val)?;
147                        pre = val;
148                    }
149                } else if bit_depth == 16 {
150                    let mut pre = writer.read_u16_be()?;
151                    for _ in 1..width {
152                        let cur = writer.peek_u16_be()?;
153                        let val = cur.wrapping_add(pre);
154                        writer.write_u16_be(val)?;
155                        pre = val;
156                    }
157                } else if bit_depth == 32 {
158                    let mut pre = writer.read_u32_be()?;
159                    for _ in 1..width {
160                        let cur = writer.peek_u32_be()?;
161                        let val = cur.wrapping_add(pre);
162                        writer.write_u32_be(val)?;
163                        pre = val;
164                    }
165                } else {
166                    anyhow::bail!("Unsupported bit depth for decompression: {}", bit_depth);
167                }
168            }
169            data.image_data = decompressed;
170            data.compression = 0;
171            Ok(())
172        }
173        _ => anyhow::bail!("Unsupported compression type: {}", data.compression),
174    }
175}